package com.dhp.bkOjjudgeservice.rabbitMQ;


import cn.hutool.json.JSONUtil;
import com.dhp.bkOjfeignclient.service.QuestionFeignClient;
import com.dhp.bkOjjudgeservice.JudgeService;
import com.dhp.bkOjjudgeservice.codesandbox.utils.RetryUtil;
import com.dhp.common.ErrorCode;
import com.dhp.constant.MQConstant;
import com.dhp.exception.BusinessException;
import com.dhp.model.entity.QuestionSubmit;
import com.dhp.model.enums.QuestionSubmitStatusEnum;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.checkerframework.checker.units.qual.A;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Component;

import java.io.IOException;

/**
 * 消息队列消费者
 */
@Component
@Slf4j
public class MessageConsumer {

    @Autowired
    private JudgeService judgeService;

    @Autowired
    private QuestionFeignClient questionFeignClient;

    @Autowired
    private RetryUtil retryUtil;

    /**
     * 消费者消息处理
     * @param message 消息
     * @param channel 连接
     * @param deliveryTag 消息头
     */
    @RabbitListener(queues = {MQConstant.QUEUE_NAME} , ackMode = "MANUAL")
    public void receiveMessage(String message , Channel channel , @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag){
        if (StringUtils.isEmpty(message)){
            log.info("消息为空");
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR , "消息为空");
        }
        QuestionSubmit questionSubmit = JSONUtil.toBean(message, QuestionSubmit.class);
        try {
            judgeService.doJudge(questionSubmit);
            channel.basicAck(deliveryTag , false);
        }catch (Exception e){
            try {
                channel.basicNack(deliveryTag , false , false);
                log.info("消费者消费失败 , 开始尝试重试");
                retryUtil.retryJudge(questionSubmit);
            } catch (Exception ex) {
                log.error("重试失败");
                //将判题状态设置为判题失败
                questionSubmit.setStatus(QuestionSubmitStatusEnum.FAIL.getValue());
                boolean update = questionFeignClient.updateById(questionSubmit);
                if (!update){
                    log.error("提交状态更新失败 , 判题中->判题失败");
                }
            }
        }

    }
}

